#include "logcatmainwindow.h"
#include "ui_logcatmainwindow.h"

#include <QTimer>

LogcatMainWindow::LogcatMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::LogcatMainWindow)
{
    ui->setupUi(this);

    // # adb 日志缓冲区: main system radio events crash default all
    // # main    - 主缓冲区
    // # system  - 系统缓冲区
    // # radio   - 无线缓冲区
    // # events  - 事件缓冲区
    // # crash   - 崩溃缓冲区
    // # default - 默认缓冲区
    // # all     - 所有缓冲区

    m_cbs.insert("all", ui->cb_all);
    connect(ui->cb_all, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("main", ui->cb_main);
    connect(ui->cb_main, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("system", ui->cb_system);
    connect(ui->cb_system, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("radio", ui->cb_radio);
    connect(ui->cb_radio, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("events", ui->cb_events);
    connect(ui->cb_events, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("crash", ui->cb_crash);
    connect(ui->cb_crash, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("default", ui->cb_default);
    connect(ui->cb_default, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("all", ui->cb_all);
    connect(ui->cb_all, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);

    m_cbs.insert("kernel", ui->cb_kernel);
    connect(ui->cb_kernel, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);
    m_cbs.insert("security", ui->cb_security);
    connect(ui->cb_security, &QCheckBox::stateChanged, this, &LogcatMainWindow::slotStateChanged);

    ui->logcat_editor->setWordWrapMode(QTextOption::WrapMode::NoWrap);
}

LogcatMainWindow::~LogcatMainWindow()
{
    delete ui;
}

void LogcatMainWindow::setLogcat(QString log)
{
//    QMap<QString, QString> m_klog;
    m_logcat.clear();
    m_klog.clear();

    // 这里通过 进行分组，将日志分为 main system radio events crash default all
    // --------- switch to main
    // .....
    // --------- switch to system
    // .....
    // --------- switch to radio
    // .....

    QString start = "--------- switch to ";
    QString start2 = "--------- beginning of ";

    QString tag = "";
    QStringList lines = log.split("\n");
    for (int i = 0; i < lines.size(); i++) {
        LogcatLine logcatLine;
        if (lines.at(i).startsWith(start)) {
            tag = lines.at(i).mid(start.length()).trimmed();
        } else if (lines.at(i).startsWith(start2)) {
            tag = lines.at(i).mid(start2.length()).trimmed();
        }
        logcatLine.tag = tag;
        logcatLine.line = lines.at(i);
        m_logcat.append(logcatLine);
    }

    // 将日志内容分别存储到 m_klog 中
    QString tag_main;
    QString tag_system;
    QString tag_radio;
    QString tag_events;
    QString tag_crash;
    QString tag_kernel;
    QString tag_security;
    for (int i = 0; i < m_logcat.size(); i++) {
        // main
        // system
        // radio
        // events
        // crash
        // default
        // all
        if (m_logcat.at(i).line.startsWith(start)) {
            continue;
        } else if (m_logcat.at(i).line.startsWith(start2)) {
            continue;
        }
        if (m_logcat.at(i).tag == "main") {
            tag_main += m_logcat.at(i).line + "\n";
        } else if (m_logcat.at(i).tag == "system") {
            tag_system += m_logcat.at(i).line + "\n";
        } else if (m_logcat.at(i).tag == "radio") {
            tag_radio+= m_logcat.at(i).line + "\n";
        } else if (m_logcat.at(i).tag == "events") {
            tag_events += m_logcat.at(i).line + "\n";
        } else if (m_logcat.at(i).tag == "crash") {
            tag_crash += m_logcat.at(i).line + "\n";
        } else if (m_logcat.at(i).tag == "kernel") {
            tag_kernel += m_logcat.at(i).line + "\n";
        } else if (m_logcat.at(i).tag == "security") {
            tag_security += m_logcat.at(i).line + "\n";
        }
    }
    m_klog.insert("main", tag_main);
    m_klog.insert("system", tag_system);
    m_klog.insert("radio", tag_radio);
    m_klog.insert("events", tag_events);
    m_klog.insert("crash", tag_crash);

    m_klog.insert("kernel", tag_kernel);
    m_klog.insert("security", tag_security);

    // 这里将日志显示到界面上

    ui->cb_all->setEnabled(m_klog.contains("all"));
    ui->cb_main->setEnabled(m_klog.contains("main"));
    ui->cb_system->setEnabled(m_klog.contains("system"));
    ui->cb_radio->setEnabled(m_klog.contains("radio"));
    ui->cb_events->setEnabled(m_klog.contains("events"));
    ui->cb_crash->setEnabled(m_klog.contains("crash"));
    ui->cb_default->setEnabled(m_klog.contains("default"));

    ui->cb_kernel->setEnabled(m_klog.contains("kernel"));
    ui->cb_security->setEnabled(m_klog.contains("security"));

    updateLog();
}

void LogcatMainWindow::setPickRange(QString start, QString stop)
{
    ui->lg_pick_start->setText(start);
    ui->lg_pick_stop->setText(stop);

    ui->cb_pick_start->setChecked(true);
    ui->cb_pick_stop->setChecked(true);
}

void LogcatMainWindow::updateLog(bool cb_slot)
{
    QStringList logs;
    int limit = 0;
    foreach (auto var, m_cbs.keys()) {
        if (m_cbs.value(var)->isEnabled())
            if (m_cbs.value(var)->isChecked())
                limit++;
    }

    QString start = "--------- switch to ";
    QString start2 = "--------- beginning of ";

    for (int i = 0; i < m_logcat.count(); ++i) {
        auto log = m_logcat.at(i);
        if (!log.tag.isEmpty()) {
            if (m_cbs.contains(log.tag))
                if (m_cbs.value(log.tag)->isChecked())
                    if (limit != 1 || (limit == 1 && !(log.line.startsWith(start) || log.line.startsWith(start2))))
                        logs << log.line;
        } else {
            if (log.tag == "all" && ui->cb_all->isChecked()) logs << log.line;
        }
    }

    if (cb_slot) {
        auto vstart = (logs.join("\n").contains(ui->lg_pick_start->text()));
        auto vstop = (logs.join("\n").contains(ui->lg_pick_stop->text()));

        ui->cb_pick_start->setChecked(vstart);
        ui->cb_pick_stop->setChecked(vstop);
    }

    if (!ui->lg_pick_start->text().isEmpty() && ui->cb_pick_start->isChecked()) {
        QString start = ui->lg_pick_start->text();
        while (logs.count()) {
            if (logs.first().contains(start, Qt::CaseInsensitive)) {
                break;
            }
            logs.removeFirst();
        }
    }

    if (!ui->lg_pick_stop->text().isEmpty() && ui->cb_pick_stop->isChecked()) {
        QString start = ui->lg_pick_stop->text();
        while (logs.count()) {
            if (logs.last().contains(start, Qt::CaseInsensitive)) {
                break;
            }
            logs.removeLast();
        }
    }

    ui->logcat_editor->setText(logs.join("\n"));
}

void LogcatMainWindow::slotStateChanged()
{
    updateLog(true);
}


void LogcatMainWindow::on_logcat_wordwrap_stateChanged(int arg1)
{
    ui->logcat_editor->setWordWrapMode((arg1 == Qt::CheckState::Checked) ? QTextOption::WrapMode::WordWrap : QTextOption::WrapMode::NoWrap);
}


void LogcatMainWindow::on_logcat_editor_slider_valueChanged(int value)
{
    auto font = ui->logcat_editor->font();
    font.setPointSize(value);
    ui->logcat_editor->setFont(font);
}


void LogcatMainWindow::on_lg_pick_start_textChanged(const QString &arg1)
{
    static QTimer timer;
    timer.disconnect();

    QObject::connect(&timer, &QTimer::timeout, [=]() {
        updateLog();
        timer.stop();
    });

    // seep 1s, call updateLog
    timer.start(1000);
}

void LogcatMainWindow::on_lg_pick_stop_textChanged(const QString &arg1)
{
    static QTimer timer;
    timer.disconnect();

    QObject::connect(&timer, &QTimer::timeout, [=]() {
        updateLog();
        timer.stop();
    });

    // seep 1s, call updateLog
    timer.start(1000);
}
